#!/usr/bin/env python
# encoding: utf-8

from decimal import Decimal
import configparser
import os
import re
import datetime

import xlrd
import copy

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

from ui.fileChange import Ui_Form as fileChangeForm

class ConditionInputWidget(QDialog):
    condition = {}

    def __init__(self):
        super().__init__()
        self.setWindowTitle("条件填写")

        self.label_raytype = QLabel('射线类型')
        self.combox_raytype = QComboBox()
        self.combox_raytype.addItems(['电子','光子'])

        self.label_raysize = QLabel('射野(cm)')
        self.lineEdit_raysize = QLineEdit('10')

        self.label_type = QLabel('类型')
        self.combox_type = QComboBox()
        self.combox_type.addItems(['PDD','OAR'])

        self.label_power = QLabel('能量(MeV/MV)')
        self.lineEdit_power = QLineEdit('6')

        self.label_deepth = QLabel('测量深度(mm)')
        self.lineEdit_deepth = QLineEdit('100')

        self.label_ssd = QLabel('源皮距(mm)')
        self.lineEdit_ssd = QLineEdit('1000')

        self.label_direction = QLabel('方向(mm)')
        self.combox_direction = QComboBox()
        self.combox_direction.addItems(['X','Y'])

        self.btn_ok = QPushButton('确定')
        self.btn_ok.clicked.connect(self.accept)
        self.btn_cancel = QPushButton('取消')
        self.btn_cancel.clicked.connect(self.reject)

        self.grid = QGridLayout()

        self.grid.addWidget(self.label_raytype,    0,0,1,1)
        self.grid.addWidget(self.combox_raytype,   0,1,1,1)
        self.grid.addWidget(self.label_raysize,    1,0,1,1)
        self.grid.addWidget(self.lineEdit_raysize, 1,1,1,1)
        self.grid.addWidget(self.label_ssd,        3,0,1,1)
        self.grid.addWidget(self.lineEdit_ssd,     3,1,1,1)
        self.grid.addWidget(self.label_power,      4,0,1,1)
        self.grid.addWidget(self.lineEdit_power,   4,1,1,1)
        self.grid.addWidget(self.btn_ok,           7,0,1,1)
        self.grid.addWidget(self.btn_cancel,       7,1,1,1)

        self.setLayout(self.grid)

    def accept(self):
        self.condition = {
            'power': self.lineEdit_power.text(),
            'time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'ray_size': self.lineEdit_raysize.text(),
            'ray_type': self.combox_raytype.currentText(),
            'ssd': self.lineEdit_ssd.text(),
        }
        QDialog.accept(self)

    def reject(self):
        QDialog.reject(self)


class FileChangeForm(QWidget,fileChangeForm):

    file_list = []

    def __init__(self,parent=None):
        super(QWidget, self).__init__(parent)
        self.setupUi(self)

        self.pushButton_selectFile.clicked.connect(self.selectFile)
        # self.pushButton_exportASC.clicked.connect(self.exportASC)
        self.pushButton_txt2asc.clicked.connect(self.txt2asc)
        self.file_list = []

        # self.inputw = ConditionInputWidget()
        # self.inputw.show()

    def selectFile(self):
        """打开项目"""
        fi = QFileDialog()
        fi.setWindowTitle("选择文件")
        fi.setDirectory(os.getcwd())
        fi.setOption(QFileDialog.DontUseNativeDialog, True)
        file_view = fi.findChild(QListView, 'listView')
        # 设置可以打开多个文件夹
        if file_view:
            file_view.setSelectionMode(QAbstractItemView.MultiSelection)
        f_tree_view = fi.findChild(QTreeView)
        if f_tree_view:
            f_tree_view.setSelectionMode(QAbstractItemView.MultiSelection)
        if fi.exec():
            file_list = fi.selectedFiles()
            if file_list:
                file_list = file_list[::-1]
                self.file_list = file_list
                for f in file_list:
                    item = QListWidgetItem("%s" % f)
                    self.listWidget.addItem(item)
            else:
                QMessageBox.information(self,'提示','未选择任何文件!',QMessageBox.Yes)

    def exportASC(self):
        if self.file_list:
            rd = self.readDataFile(self.file_list[0])
            conf = rd['condition']
            power = conf['power'].replace('MV','').replace('MeV','')
            pdd_oar = 'pdd' if conf['type']=='PDD' else 'pro'
            size = str(int(float(conf['ray_size_x'].replace('cm',''))))
            filename = power + pdd_oar + size

            exp_dir = QFileDialog.getSaveFileName(self,
                                                       "请选择数据导出路径!",
                                                       '%s/%s.ASC'%(os.getcwd(),filename))
            if exp_dir:
                txt = self.readFile('tmp.ASC', self.file_list)
                self.writeFile(exp_dir[0], txt)
                QMessageBox.information(self,'提示','导出成功！',QMessageBox.Yes)
        else:
            QMessageBox.warning(self,'提示','未选择要导出的文件！',QMessageBox.Yes)

    def readDataFile(self, file_path=''):
        """读取项目文件中数据

        :param file_name: 文件名
        :return:
        """
        try:
            config = configparser.ConfigParser()
            config.read(file_path)
            condition = dict(config['condition'])
            data = dict(config['data'])
            # 根据键值序号排序
            data_list = [[int(k),data[k]] for k in data.keys()]
            data_list = sorted(data_list)
            # 生成最后数据 [['1','2',],[]]
            data_new = [d[1].replace('[', '').replace(']', '').split(',') for d in data_list]
            return {'condition': condition, 'data': data_new}
        except:
            return False

    def readFile(self, tmp_file, file_list):
        with open(tmp_file, 'r') as f:
            lines = f.readlines()
            header = lines[:2]
            body = lines[2:-1]
            end = lines[-1]

            def deal_body(lines, conf, data, number):
                txt = ''
                for i in range(0, len(lines)):
                    l = str(lines[i])
                    if l.find('Measurement number') > 0:
                        l = l.replace('1', str(number))
                    if l.find('VNR') > 0:
                        l = l.replace('1.0', '1.1')
                    if l.find('DAT') > 0:
                        l = l.replace('03-22-2015', conf['time'][5:10]+'-'+conf['time'][:4])
                    if l.find('TIM') > 0:
                        l = l.replace('13:48:53', conf['time'][-8:])
                    if l.find('BMP') > 0:
                        l = l.replace('6.0', '%.1f'%float(conf['power'].replace('MeV','').replace('MV','')))
                    if l.find('SCN') > 0:
                        if conf['type'] == 'PDD':
                            l = l.replace('DPT','DPT')
                        if conf['type'] == 'OAR':
                            l = l.replace('DPT','PRO')
                    if l.find('FSZ') > 0:
                        l = l.replace('40', str(int(float(conf['ray_size_x'])*10)))
                        l = l.replace('41', str(int(float(conf['ray_size_y'])*10)))
                    if l.find('SSD') > 0:
                        l = l.replace('1000', str(int(float(conf['ssd'][:-2])*10)))
                    if l.find('PRD') > 0:
                        l = l.replace('0', '%s'%(conf['deepth'].replace('mm','')))
                    if l.find('PTS') > 0: # 测量数据个数
                        l = l.replace('270', str(len(data)))
                    if l.find('STS') > 0:
                        x = float(data[-1][0])
                        y = float(data[-1][1])
                        z = float(data[-1][2])
                        l = l.replace('0.0', str('%.1f'%float(x))).replace('0.1', str('%.1f'%float(y))).replace('0.2', str('%.1f'%float(z)))
                    if l.find('EDS') > 0:
                        x = float(data[0][0])
                        y = float(data[0][1])
                        z = float(data[0][2])
                        l = l.replace('0.0', str('%.1f'%float(x))).replace('0.1', str('%.1f'%float(y))).replace('0.2', str('%.1f'%float(z)))
                    if l.find('=') >= 0:
                        if conf['type'] == 'PDD':
                            tm = [float(d[3]) for d in data]
                            ts = [float(d[4]) for d in data]
                            repeat  = [float('%.4f'%(m/(s+0.00000001))) for m,s in zip(tm,ts)]
                            normal = [float('%.4f'%(100*r/max(repeat))) for r in repeat]
                            s = ''
                            for i in range(0, len(data)):
                                d = data[len(data)-i-1]
                                x = d[0]
                                y = d[1]
                                z = d[2]
                                n = normal[len(data)-i-1]
                                s += '=  '+'%8.1f%8.1f%8.1f%8.1f\n'%(
                                    Decimal(d[0]).quantize(Decimal('0.0')),
                                    Decimal(d[1]).quantize(Decimal('0.0')),
                                    Decimal(d[2]).quantize(Decimal('0.0')),
                                    Decimal(n).quantize(Decimal('0.0')))
                            txt += s
                        if conf['type'] == 'OAR':
                            tm = [float(d[3]) for d in data]
                            ts = [float(d[4]) for d in data]

                            zero_pos = int(len(data)/2)+1

                            tm_l = tm[:zero_pos]
                            ts_l = ts[:zero_pos]

                            tm_r = tm[zero_pos:]
                            ts_r = ts[zero_pos:]

                            repeat_l = [float('%.4f'%(m/s)) for m,s in zip(tm_l,ts_l)]
                            repeat_r = [float('%.4f'%(m/s)) for m,s in zip(tm_r,ts_r)]

                            repeat  = repeat_l + repeat_r
                            # 中心点位置进行归一化

                            left_data = repeat[:zero_pos]
                            normal_l = [float('%.4f'%(100*r/repeat_l[len(repeat_l)-1])) for r in repeat_l]

                            right_data = repeat[zero_pos:]
                            normal_r = [float('%.4f'%(100*r/repeat_r[0])) for r in repeat_r]

                            # normal = [float('%.4f'%(100*r/repeat[zero_pos])) for r in repeat]
                            normal = normal_l + normal_r

                            repeat  = [float('%.4f'%(m/(s+0.00000001))) for m,s in zip(tm,ts)]
                            normal = [float('%.4f'%(100*r/max(repeat))) for r in repeat]
                            s = ''
                            for i in range(0, len(data)):
                                d = data[len(data)-i-1]
                                x = d[0]
                                y = d[1]
                                z = d[2]
                                n = normal[len(data)-i-1]
                                s += '=  '+'%8.1f%8.1f%8.1f%8.1f\n'%(
                                    Decimal(d[0]).quantize(Decimal('0.0')),
                                    Decimal(d[1]).quantize(Decimal('0.0')),
                                    Decimal(d[2]).quantize(Decimal('0.0')),
                                    Decimal(n).quantize(Decimal('0.0')))
                            txt += s
                    else:
                        txt += l
                return txt

            content = ''
            for h in header:
                if h.find('MSR') > 0:
                    h = h.replace('1',str(len(file_list)))
                content += h

            for i in range(0, len(file_list)):
                f = file_list[i]
                rd = self.readDataFile(f)
                conf = rd['condition']
                data = rd['data']
                number = i+1
                content += deal_body(body, conf, data, number)
            content += end
            return content

    def writeFile(self, filename, txt):
        with open(filename, 'w') as f:
            f.write(txt)

    def txt2asc(self):
        file_list = []
        for i in range(self.listWidget.count()):
            item = self.listWidget.item(i)
            file_list.append(item.text())

        if not file_list:
            QMessageBox.information(self,'提示','请选择要导出的文件！',QMessageBox.Yes)
            return

        conf = None
        inputDlg = ConditionInputWidget()
        if inputDlg.exec() == QDialog.Accepted:
            conf = inputDlg.condition
        else:
            QMessageBox.information(self,'提示','条件未填写！',QMessageBox.Yes)
            return

        try:
            deal_list = []
            for file in file_list:
                if str(file).endswith('.xls'):
                    workbook = xlrd.open_workbook(file)
                    sheet    = workbook.sheet_by_index(0)
                    # 获取数据
                    pos_data = sheet.col_values(1)[2:]
                    dos_data = sheet.col_values(2)[2:]
                    conf_data = sheet.col_values(8)[1:]
                    num_reg = '^([0-9]{1,})'
                    float_reg = '^([0-9]{1,}[.][0-9]*)'
                    conf['power'] = re.match(num_reg,conf_data[1]).group(1)
                    conf['ssd'] = '%s'%(10*int(re.match(num_reg,conf_data[2]).group(1)))
                    print(conf['ssd'])
                    if conf_data[3] == 'A->B' or conf_data[3] == 'B->A':
                        conf['direction'] = 'X'
                        conf['type'] = 'OAR'
                    elif conf_data[3] == 'G->T' or conf_data[3] == 'T->G':
                        conf['direction'] = 'Y'
                        conf['type'] = 'OAR'
                    elif conf_data[3] == 'O->G':
                        conf['direction'] = 'Z'
                        conf['type'] = 'PDD'
                    conf['deepth'] = re.match(num_reg,conf_data[4]).group(1)
                    print(conf['deepth'])
                    deepth = conf['deepth']
                    data = []
                    for pos, dos in zip(pos_data, dos_data):
                        direction = conf['direction']
                        if direction == "X":
                            data.append([pos,0,float(deepth), float(dos)])
                        elif direction == "Y":
                            data.append([0,pos,float(deepth), float(dos)])
                        else:
                            data.append([0,0,float(pos), float(dos)])
                    # deal_list.append({
                        # 'condition': conf,
                        # 'data': data
                    # })
                if str(file).endswith('.txt'):
                    c = str(file).split('/')
                    name = c[-1]
                    res = re.match('^([0-9]{1,}).*?D([0-9]{1,})mm-([a-zA-Z])',name, re.M|re.I)
                    if not res:
                        QMessageBox.information(self,'提示','文件:%s \r\n格式不符合'%file,QMessageBox.Yes)

                    ray_size = res.group(1)
                    deepth = res.group(2)
                    direction = res.group(3)
                    conf['ray_size'] = ray_size
                    conf['deepth'] = deepth
                    print(conf['deepth'])
                    conf['direction'] = direction
                    with open(file, 'r') as f:
                        data = []
                        for line in f.readlines():
                            res = re.match('^(-?[0-9]{1,}[.][0-9]*)([\s]{1,})([0-9]{1,}[.][0-9]*)',line, re.M|re.I)
                            if res:
                                pos = res.group(1)
                                dos = res.group(3)
                                if direction == "X":
                                    conf['type'] = 'OAR'
                                    data.append([pos,0,float(deepth), float(dos)])
                                if direction == "Y":
                                    conf['type'] = 'OAR'
                                    data.append([0,pos,float(deepth), float(dos)])
                # 这里要用copy，不然字典的值是一样的
                tmp = copy.deepcopy(conf)
                deal_list.append({
                    'condition': tmp,
                    'data': data
                })

            if len(deal_list)>0:
                conf = deal_list[0]['condition']
                pdd_oar = 'pdd' if conf['type']=='PDD' else 'pro'
                size = conf['ray_size']
                print('射野：'+size)
                power = conf['power']
                filename = power + pdd_oar + size

                exp_dir = QFileDialog.getSaveFileName(self, "请选择数据导出路径!", '%s/%s.ASC'%(os.getcwd(),filename))
                if exp_dir[0]:
                    txt = self.readFileTxt('tmp.ASC', deal_list)
                    self.writeFile(exp_dir[0], txt)
                    QMessageBox.information(self,'提示','导出成功！',QMessageBox.Yes)
        except Exception as e:
            QMessageBox.information(self,'错误',str(e),QMessageBox.Yes)


    def readFileTxt(self, tmp_file, file_list):
        with open(tmp_file, 'r') as f:
            lines = f.readlines()
            header = lines[:2]
            body = lines[2:-1]
            end = lines[-1]

            def deal_body(lines, conf, data, number):
                txt = ''
                for i in range(0, len(lines)):
                    l = str(lines[i])
                    if l.find('Measurement number') > 0:
                        l = l.replace('1', str(number))
                    if l.find('VNR') > 0:
                        l = l.replace('1.0', '1.1')
                    if l.find('DAT') > 0:
                        l = l.replace('03-22-2015', conf['time'][5:10]+'-'+conf['time'][:4])
                    if l.find('TIM') > 0:
                        l = l.replace('13:48:53', conf['time'][-8:])
                    if l.find('BMP') > 0:
                        l = l.replace('6.0', '%.1f'%float(conf['power'].replace('MeV','').replace('MV','')))
                    if l.find('SCN') > 0:
                        if conf['type'] == 'PDD':
                            l = l.replace('DPT','DPT')
                        if conf['type'] == 'OAR':
                            l = l.replace('DPT','PRO')
                    if l.find('FSZ') > 0:
                        l = l.replace('40', str(int(float(conf['ray_size'])*10)))
                        l = l.replace('41', str(int(float(conf['ray_size'])*10)))
                    if l.find('SSD') > 0:
                        l = l.replace('1000', str(int(float(conf['ssd']))))
                    if l.find('PRD') > 0:
                        l = l.replace('0', '%s'%(conf['deepth'].replace('mm','')))
                    if l.find('PTS') > 0: # 测量数据个数
                        l = l.replace('270', str(len(data)))
                    if l.find('STS') > 0:
                        x = float(data[-1][0])
                        y = float(data[-1][1])
                        z = float(data[-1][2])
                        l = l.replace('0.0', str('%.1f'%float(x))).replace('0.1', str('%.1f'%float(y))).replace('0.2', str('%.1f'%float(z)))
                    if l.find('EDS') > 0:
                        x = float(data[0][0])
                        y = float(data[0][1])
                        z = float(data[0][2])
                        l = l.replace('0.0', str('%.1f'%float(x))).replace('0.1', str('%.1f'%float(y))).replace('0.2', str('%.1f'%float(z)))
                    if l.find('=') >= 0:
                        s = ''
                        for i in range(0, len(data)):
                            d = data[len(data)-i-1]
                            x = d[0]
                            y = d[1]
                            z = d[2]
                            n = d[3]
                            s += '=  '+'%8.1f%8.1f%8.1f%8.1f\n'%(
                                Decimal(d[0]).quantize(Decimal('0.0')),
                                Decimal(d[1]).quantize(Decimal('0.0')),
                                Decimal(d[2]).quantize(Decimal('0.0')),
                                Decimal(n).quantize(Decimal('0.0')))
                        txt += s
                    else:
                        txt += l
                return txt

            content = ''
            for h in header:
                if h.find('MSR') > 0:
                    h = h.replace('1',str(len(file_list)))
                content += h

            for i in range(0, len(file_list)):
                f = file_list[i]

                # rd = self.readDataFile(f)
                conf = f['condition']
                data = f['data']

                number = i+1
                content += deal_body(body, conf, data, number)
            content += end
            return content


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    win = FileChangeForm()
    win.show()
    app.exec_()

